﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

public class MessageController  {
    private static MessageController instance;


    private MessageController()
    {

    }
    public static MessageController GetInstance()
    {
        if (instance == null)
        {
            instance = new MessageController();
        }
        return instance;
    }

    //单包拆解
    public KeyValuePair<short,byte[]> ReadMessage(byte[] message,int length)
    {
        //拷贝消息类型  short类型,前2个字节
        byte[] type = new byte[2];
        Buffer.BlockCopy(message,0,type,0,2);
        //拷贝消息内容  object类型，拿出来后转json
        byte[] content = new byte[length - 2];
        Buffer.BlockCopy(message, 2, content, 0, length - 2);
        short Type = BitConverter.ToInt16(type, 0);
        return new KeyValuePair<short, byte[]>(Type, content);

    }

    /// <summary>
    /// 粘包处理方法
    /// </summary>
    /// <param name="message">数据包</param>
    /// <param name="length">有效长度</param>
    /// <returns></returns>
    public Dictionary<short, byte[]> ReadPasteMessage(byte[] message, int length)
    {
        Dictionary<short, byte[]> messages = new Dictionary<short, byte[]>();
        //拆包
        int _leftlength = length;
        try
        {
            do
            {
                byte[] _head = new byte[4];
                //将数据包的前四个字节复制出来
                Buffer.BlockCopy(message, 0, _head, 0, 4);
                _leftlength -= 4;

                byte[] _type = new byte[2];
                //将数据包的第5个至第6个字节复制出来
                Buffer.BlockCopy(message, 4, _type, 0, 2);

                //字节数组前4个字节转换为int后的数字为，type长度 + 内容长度
                //讲head所包含的int 减去short所占的长度，剩余的即为内容字节数组所占长度
                int currentLength = BitConverter.ToInt32(_head, 0) - 2;
                _leftlength -= 2;
                byte[] _content = new byte[currentLength];
                Buffer.BlockCopy(message, 6, _content, 0, currentLength);

                //添加到字典
                messages.Add(BitConverter.ToInt16(_type, 0), _content);
                _leftlength -= currentLength;
            } while (_leftlength > 0);
        }
        catch (Exception)
        {
            //解析报错
        }

        return messages;
    }

    #region 其他类型转Bytes

    /// <summary>
    /// 写入信息转bye[]，返回
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="K"></typeparam>
    /// <param name="_type">消息类型</param>
    /// <param name="_message">消息内容</param>
    /// <returns></returns>
    public byte[] WriteMessage(short _type,string _message)
    {
        byte[] content = Encoding.ASCII.GetBytes(_message);
        return CombineByteArray(_type,content);
    }

    /// <summary>
    /// 带字节数组长度，合并数据到一个包体内
    /// </summary>
    /// <param name="type"></param>
    /// <param name="content"></param>
    /// <returns></returns>
    public byte[] CombineByteArray(short type,byte[] content)
    {
        //获取数据类型字节数组
        byte[]  Type = BitConverter.GetBytes(type);
        //获取数据包长度
        int headlength = Type.Length + content.Length;
        byte[] head = BitConverter.GetBytes(headlength);
        //完整包
        byte[] message = new byte[head.Length + Type.Length + content.Length];

        //全部粘到一个包内
        Buffer.BlockCopy(head, 0, message, 0, head.Length);
        Buffer.BlockCopy(Type, 0, message, 4, Type.Length);
        Buffer.BlockCopy(content, 0, message, 6, content.Length);
        return message;
    }
    
    /// <summary>
    /// int类型写入数据
    /// </summary>
    /// <param name="_type">类型</param>
    /// <param name="_message">数据包</param>
    /// <returns></returns>
    public byte[] WriteMessage(short _type, int _message)
    {
        byte[] content = BitConverter.GetBytes(_message);
        return CombineByteArray(_type,content);
    }
    /// <summary>
    /// short类型写入数据
    /// </summary>
    /// <param name="_type">类型</param>
    /// <param name="_message">数据包</param>
    /// <returns></returns>
    public byte[] WriteMessage(short _type, short _message)
    {
        byte[] content = BitConverter.GetBytes(_message);
        return CombineByteArray(_type, content);
    }
    /// <summary>
    /// int[]类型写入数据
    /// </summary>
    /// <param name="_type">类型</param>
    /// <param name="_message">数据包</param>
    /// <returns></returns>
    public byte[] WriteMessage(short _type, int[] _message)
    {
        byte[] content = new byte[_message.Length * 4];
        for (int i = 0; i < _message.Length; i++)
        {
            byte[] temp = BitConverter.GetBytes(_message[i]);
            Buffer.BlockCopy(temp,0, content, i * 4,temp.Length);
        }
        return CombineByteArray(_type, content);
    }
    /// <summary>
    /// short[]类型写入数据
    /// </summary>
    /// <param name="_type">类型</param>
    /// <param name="_message">数据包</param>
    /// <returns></returns>
    public byte[] WriteMessage(short _type, short[] _message)
    {
        byte[] content = new byte[_message.Length * 2];
        for (int i = 0; i < _message.Length; i++)
        {
            byte[] temp = BitConverter.GetBytes(_message[i]);
            Buffer.BlockCopy(temp, 0, content, i * 2, temp.Length);
        }
        return CombineByteArray(_type, content);
    }
    #endregion

    #region Byte转其他类型
    public string GetStrFromBytes(byte[] content)
    {
        return Encoding.ASCII.GetString(content);
    }

    public int GetIntFromBytes(byte[] content)
    {
        return BitConverter.ToInt32(content, 0);
    }
    public short GetShortFromBytes(byte[] content)
    {
        return BitConverter.ToInt16(content, 0);
    }
    public int[] GetIntArrayFromBytes(byte[] content)
    {
        int[] MyArray_rezult_i = new int[content.Length / 4];
        for (int i = 0; i < MyArray_rezult_i.Length; i++)
        {
            byte[] temp= new byte[4];
            Buffer.BlockCopy(content,i * 4,temp,0,4);
            MyArray_rezult_i[i] = BitConverter.ToInt32(temp,0);
        }
        return MyArray_rezult_i;
    }
    public short[] GetShortArrayFromBytes(byte[] content)
    {
        short[] MyArray_rezult_s = new short[content.Length / 2];
        for (int i = 0; i < MyArray_rezult_s.Length; i++)
        {
            byte[] temp = new byte[4];
            Buffer.BlockCopy(content, i * 4, temp, 0, 4);
            MyArray_rezult_s[i] = BitConverter.ToInt16(temp, 0);
        }
        return MyArray_rezult_s;
    }
#endregion
}
